/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.aqq;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TabActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.BaseAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ExpandableListView.OnChildClickListener;

import com.android.aqq.bean.BuddyGroup;
import com.android.aqq.bean.ChatState;
import com.android.aqq.bean.QQBuddy;
import com.android.aqq.bean.QQGroup;
import com.android.aqq.bean.QQGroupMember;
import com.android.aqq.bean.SortList;
import com.android.aqq.bean.VerifyImage;
import com.android.aqq.bean.ViewHolder;
import com.android.aqq.util.QQEventUtils;
import com.android.aqq.util.Utils;

import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.QQClient;
import edu.tsinghua.lumaqq.qq.Util;
import edu.tsinghua.lumaqq.qq.beans.ClusterIM;
import edu.tsinghua.lumaqq.qq.beans.ContactInfo;
import edu.tsinghua.lumaqq.qq.beans.FriendOnlineEntry;
import edu.tsinghua.lumaqq.qq.beans.FriendRemark;
import edu.tsinghua.lumaqq.qq.beans.FriendStatus;
import edu.tsinghua.lumaqq.qq.beans.QQUser;
import edu.tsinghua.lumaqq.qq.events.QQEvent;
import edu.tsinghua.lumaqq.qq.packets.Packet;
import edu.tsinghua.lumaqq.qq.packets.in.AddFriendExReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.AuthInfoOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.FriendChangeStatusPacket;
import edu.tsinghua.lumaqq.qq.packets.in.FriendDataOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetOnlineOpReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.GetUserInfoReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.lumaqq.qq.packets.in.SystemNotificationPacket;
import edu.tsinghua.lumaqq.qq.packets.out.AuthInfoOpPacket;
import edu.tsinghua.lumaqq.qq.packets.out.FriendDataOpPacket;

public class aQQActivity extends TabActivity {
	private static final int DIALOG_MESSAGE = 0;
	private static final int DIALOG_CONFIRM = 1;
	private static final int DIALOG_ADD_FRIEND = 2;
	private static final int DIALOG_ADD_FRIEND_OK = 3;
	private static final int DIALOG_ADD_FRIEND_AUTH = 4;
	private static final int DIALOG_SELECT_GROUP = 5;
	private static final int DIALOG_MODIFY_REMARK = 6;
	private static final int DIALOG_ABOUT = 7;
	public static final int NOTIFICATION_STATUS = 0;
	public static final int NOTIFICATION_QQGROUP_CHAT = 1;
	public static final int NOTIFICATION_FRIEND_CHAT = 2;
	public static final int NOTIFICATION_SYS = 3;
	private static final String NAME = "NAME";
	public static QQClient client = null;
	private String message = "";
	public static QQUser user = null;
	private static Map<Integer, Handler> handlers = new HashMap<Integer, Handler>();
	private MyExpandableListAdapter mFriendsAdapter;
	private QQGroupListAdapter mQQGroupAdapter;
	private ChatingListAdapter mChatingAdapter;
	private List<BuddyGroup> mGroupData = null;
	private List<SortList<QQBuddy>> mChildData = null;
	private Map<Integer, Integer> mBuddyGroupMap = null; //QQ号, 分组位置
	private List<QQGroup> mQQGroups = null;
	public static Map<Integer, ChatState> mChatStateMap = null;
	private ExpandableListView mFriendListView = null;
	private ListView mChatingListView = null;
	private ListView mQQGroupListView = null;
	private NotificationManager mNotificationManager;
	private Map<Integer, QQBuddy> mBuddyMap = null; //好友QQ号与名称对应QQFriendBean
	private Menu mMenu;
	private AutoCompleteTextView mSearchEdit;
	private QQService mBoundService;
//	private int friendsRemarkPage = 0;
//	private boolean hasRemark = true;
	private TabHost mTabHost;
	private int operateQQ; //当前正在操作的好友的qq号
	private SharedPreferences mSharedPref;
	private boolean isMute = false;
	private boolean isVibrate = false;
	private boolean receiveGroupIm = false;
	private View mSearchFriendsView;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mTabHost = this.getTabHost();
        
        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("好友列表").setContent(R.id.friends_view));
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("群/讨论组").setContent(R.id.groups_view));
        mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("正在聊天").setContent(R.id.chating_view));
        mTabHost.setCurrentTab(0);
        
        //初始化属性
        mFriendListView = (ExpandableListView) findViewById(R.id.user_list_view); //好友列表
        mChatingListView = (ListView) findViewById(R.id.chating_list_view); //正在聊天列表
        mQQGroupListView = (ListView) findViewById(R.id.qqgroup_list_view); //qq群列表
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mSearchEdit = (AutoCompleteTextView) findViewById(R.id.search_edit);
        mSharedPref = PreferenceManager.getDefaultSharedPreferences(aQQActivity.this);
        isMute = mSharedPref.getBoolean("MUTE_LOGIN", false);
        isVibrate = mSharedPref.getBoolean("vibrate_preference", false);
        receiveGroupIm = mSharedPref.getBoolean("RECEIVE_GROUP_IM", false);

    	//绑定QQService，设置service的controlHandler
		Intent intent = new Intent(aQQActivity.this, QQService.class);
		startService(intent);
		bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
		
		mFriendListView.setOnChildClickListener(new OnChildClickListener() {
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				final QQBuddy friend = mFriendsAdapter.getChild(groupPosition, childPosition);

				if (user==null || !user.isLoggedIn()) {
					Toast.makeText(aQQActivity.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
					return false;
				}
				
				//开启一个聊天窗口
				startChatWindow(friend);
				
/*				new AlertDialog.Builder(aQQ.this).setTitle(R.string.title_choose).setItems(R.array.item_operate,
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							switch (which) {
							case 0:
								//开启一个聊天窗口
								startChatWindow(friend);
								break;
							case 1:
								friendQQ = friend.getQQ();
								showDialog(DIALOG_SELECT_GROUP);
								break;
							case 2:
								friendQQ = friend.getQQ();
								showDialog(DIALOG_MODIFY_REMARK);
								break;
							}
						}
					}).setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
	                    public void onClick(DialogInterface dialog, int whichButton) {
	                    }
	                }).show();*/
				return false;
			}
		});
		
		mQQGroupListView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView parent, View v,
					int position, long id) {
				
				QQGroup qqGroup = mQQGroupAdapter.getItem(position);

				//开启一个聊天窗口
				startClusterChatWindow(qqGroup);
				
			}
		});
		
		mChatingListView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView av, View v,
					int position, long id) {
				ChatingListAdapter adapter = (ChatingListAdapter) av.getAdapter();
				
				ChatState chatState = adapter.getItem(position);
				
				if (chatState.getType() == 1) { //好友聊天
					QQBuddy friend = chatState.getBuddy();

					//开启一个聊天窗口
					startChatWindow(friend);
				} else { //群聊天
					QQGroup qqGroup = chatState.getQQGroup();

					//开启一个聊天窗口
					startClusterChatWindow(qqGroup);
				}
			}
		});
		mSearchFriendsView = (View) findViewById(R.id.search_friends_view);
		mSearchEdit.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> av, View v, int position,
					long id) {
				FriendsListAdapter adapter = (FriendsListAdapter) av.getAdapter();
				
				QQBuddy friend = adapter.getFriends().get(position);
				
				//开启一个聊天窗口
				startChatWindow(friend);
				
				mSearchEdit.setText("");
				mSearchFriendsView.setVisibility(View.INVISIBLE);
			}
		});
		
		final ImageView imageView = (ImageView) findViewById(R.id.search_bar);
        imageView.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if (mSearchFriendsView.getVisibility() == View.VISIBLE) {
					mSearchFriendsView.setVisibility(View.INVISIBLE);
				}
				else {
					mSearchFriendsView.setVisibility(View.VISIBLE);
				}
				
			}
        	
        });
		
//		mSearchEdit.addTextChangedListener(new TextWatcher() {
//
//			public void afterTextChanged(Editable s) {
//			}
//
//			public void beforeTextChanged(CharSequence s, int start, int count,
//					int after) {
//			}
//
//			public void onTextChanged(CharSequence s, int start, int before,
//					int count) {
//				String text = s.toString();
//				if (mAdapter != null) {
//					mAdapter.filter(text);
//					mAdapter.notifyDataSetChanged();
//					mFriendListView.setAdapter(mAdapter);
//					int size = mAdapter.getGroupCount();
//					for (int i=0; i< size; i++) {
//						mFriendListView.expandGroup(i);
//					}
//				}
//			}
//		});
		
    }
    
	private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mBoundService = ((QQService.LocalBinder)service).getService();
            mBoundService.setControlHandler(mHandler);
            
            mGroupData = mBoundService.getGroupData();
            mChildData = mBoundService.getChildData();
            mBuddyGroupMap = mBoundService.getBuddyGroupMap();
            mBuddyMap = mBoundService.getBuddyMap();
            mQQGroups = mBoundService.getQQGroups();
            mChatStateMap = mBoundService.getChatStates();
            client = mBoundService.getClient();
            user = mBoundService.getUser();
    		
    		mFriendsAdapter = new MyExpandableListAdapter(mGroupData, mChildData);
    		mFriendListView.setAdapter(mFriendsAdapter);
    		mQQGroupAdapter = new QQGroupListAdapter(aQQActivity.this);
    		mQQGroupListView.setAdapter(mQQGroupAdapter);
    		
    		fillAutoCompleteEdit();
    		
    		mChatingAdapter = new ChatingListAdapter(aQQActivity.this);
    		mChatingListView.setAdapter(mChatingAdapter);
            
    		setTitle(user.getContactInfo().nick + " " + user.getContactInfo().qq);
            
            //获取在线好友列表
			client.user_GetOnline();
			if (QQService.hasRemark) {
				//获取好友备注
				Log.d("aQQ", "friendsRemarkPage = " + QQService.friendsRemarkPage);
				client.user_GetRemarks(QQService.friendsRemarkPage);
			} else {
//				//好友排序
//				for (int i=0; i<mChildData.size(); i++) {
//					Collections.sort(mChildData.get(i), Comparators.getComparator());
//				}
			}
        }

        public void onServiceDisconnected(ComponentName className) {
            mBoundService = null;
        }
    };
    
	private void startChatWindow(QQBuddy friend) {
		if (user==null || !user.isLoggedIn()) {
			Toast.makeText(aQQActivity.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
			return;
		}
		ChatState chatState = mChatStateMap.get(friend.getQQ());
		if (chatState == null) {
			chatState = new ChatState(friend);
			mChatStateMap.put(friend.getQQ(), chatState);
			mChatingAdapter = new ChatingListAdapter(aQQActivity.this);
    		mChatingListView.setAdapter(mChatingAdapter);
		} else {
			chatState.setBuddy(friend);
		}
		
		Intent intent = new Intent(aQQActivity.this, ChatWindowActivity.class);
		intent.putExtra("FRIEND", friend);
		intent.putExtra("MYQQ", user.getQQ());
		startActivityIfNeeded(intent, 1);
	}
	
	private void startClusterChatWindow(QQGroup qqGroup) {
		if (user==null || !user.isLoggedIn()) {
			Toast.makeText(aQQActivity.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
			return;
		}
		ChatState chatState = mChatStateMap.get(qqGroup.getClusterId());
		if (chatState == null) {
			chatState = new ChatState(qqGroup);
			mChatStateMap.put(qqGroup.getClusterId(), chatState);
			mChatingAdapter = new ChatingListAdapter(aQQActivity.this);
    		mChatingListView.setAdapter(mChatingAdapter);
		} else {
			chatState.setQQGroup(qqGroup);
		}
		
		Intent intent = new Intent(aQQActivity.this, GroupChatWindowActivity.class);
		intent.putExtra("QQ_GROUP", qqGroup);
		intent.putExtra("MYQQ", user.getQQ());
		startActivityIfNeeded(intent, 1);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == 1) {
			if (resultCode == RESULT_CANCELED) {
				mChatingAdapter = new ChatingListAdapter(aQQActivity.this);
	    		mChatingListView.setAdapter(mChatingAdapter);
			}
        }
	}

	private void fillAutoCompleteEdit() {
		if (mChildData == null) return;
		int size = mChildData.size();
		final List<QQBuddy> list = new ArrayList<QQBuddy>();
		for (int i=0; i<size; i++) {
			list.addAll(mChildData.get(i));
		}
		FriendsListAdapter adapter = new FriendsListAdapter(this, list);
		mSearchEdit.setAdapter(adapter);
	}
    
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
        	QQEvent event = (QQEvent) msg.obj;
        	switch(msg.what) {
            case QQEvent.FRIEND_GET_ONLINE_OK: //得到在线好友列表成功
    			processOnlineFriends((GetOnlineOpReplyPacket) event.getSource());
    			break;
            case QQEvent.FRIEND_GET_REMARKS_OK: //得到好友备注成功
            	processFriendsRemark((FriendDataOpReplyPacket) event.getSource());
            	break;
            case QQEvent.USER_STATUS_CHANGE_OK:
            	break;
            case QQEvent.FRIEND_STATUS_CHANGED: //好友状态变化
            	processFriendChangeStatus((FriendChangeStatusPacket) event.getSource());
            	break;
            case QQEvent.FRIEND_PROPERTY_CHANGED: //好友属性变化
            	break;
            case QQEvent.USER_GET_INFO_OK: //得到用户信息成功
            	processGetUserInfo(((GetUserInfoReplyPacket) event.getSource()).contactInfo);
            	break;
            case QQEvent.IM_DUPLICATED: //收到一条重复消息
            	break;
            /*   消息通知       */
            case QQEvent.IM_RECEIVED: //收到一个普通消息
            	processNormalMessage(msg);
            	break;
            case QQEvent.IM_CLUSTER_RECEIVED: //群消息
            	if (receiveGroupIm) {
            		processGroupIm(msg);
            	}
            	break;
            case QQEvent.FRIEND_ADD_OK: //添加一个好友成功
            	int qq = ((AddFriendExReplyPacket) event.getSource()).friendQQ;
            	QQBuddy buddy = mBuddyMap.get(qq);
            	if (buddy != null) {
            		switch(buddy.verifyFlag) {
            		case QQ.QQ_AUTH_ALREADY: //对方请求加我好友并允许我加对方好友，我提交通过后把对方加好友，这样就不需要发送 AuthInfoOpPacket
            			processFriendAddOk(qq);
            			break;
            		default: //我加对方好友，对方允许任意人加好友，需要发送 AuthInfoOpPacket
            			processFriendAddGetAuth((AddFriendExReplyPacket) event.getSource());
            			break; 
            		}
            	}
            	break;
            case QQEvent.SYS_APPROVE_ADD_BIDI: //
            	processFriendAddOk(((SystemNotificationPacket) event.getSource()).from);
            	break;
            case QQEvent.FRIEND_ADD_NO_AUTH:
            case QQEvent.FRIEND_ADD_NEED_AUTH:
            	processFriendAddGetAuth((AddFriendExReplyPacket) event.getSource());
            	break;
            case QQEvent.FRIEND_GET_AUTH_INFO_OK:
            	sendFriendAddAuthInfo((AuthInfoOpReplyPacket) event.getSource());
            	break;
            case QQEvent.FRIEND_GET_AUTH_INFO_FROM_URL:
            	processGetAuthInfoFromUrl((AuthInfoOpReplyPacket) event.getSource());
            	break;
            case QQEvent.FRIEND_SUBMIT_AUTO_INFO_OK:
            	sendFriendAddAuthInfo((AuthInfoOpReplyPacket) event.getSource());
            	break;
            case QQEvent.FRIEND_UPLOAD_REMARKS_OK: //修改备注成功
            	updateBuddyRemark((FriendDataOpPacket) event.getSource()); 
            	break;
            case QQEvent.FRIEND_UPLOAD_GROUPS_OK: //上传好友分组成功
            	break;
            case QQEvent.SYS_TIMEOUT:
            	Packet p = (Packet) event.getSource();
            	message = p.getPacketName() + " 操作超时";
            	Toast.makeText(aQQActivity.this, message, Toast.LENGTH_LONG).show();
            	break;
        	default:
    			message = Integer.toHexString(msg.what)  + "：" + QQEventUtils.getQQEventDesc(msg.what, event.getSource());
        		Toast.makeText(aQQActivity.this, message, Toast.LENGTH_LONG).show();
        		break;
        	}
        }

		/**
		 * 处理获得用户信息的事件
		 * 
		 * @param contactInfo
		 */
		private void processGetUserInfo(ContactInfo contactInfo) {
			//更新好友列表的好友名称
			int qq = contactInfo.qq;
			QQBuddy friend = mBuddyMap.get(qq);
			if (friend != null) {
				friend.setContactInfo(contactInfo);
			}

			//更新正在聊天列表的好友名称
			ChatState chat = mChatStateMap.get(qq);
			if (chat != null) {
				chat.setBuddy(friend);
			}
			mFriendsAdapter.notifyDataSetChanged();
			mChatingAdapter.notifyDataSetChanged();
		}
        
        private void processFriendAddGetAuth(AddFriendExReplyPacket packet) {
        	int friendQQ = packet.friendQQ;
        	Log.d("aQQ", "friendQQ =" + packet.friendQQ);
        	AuthInfoOpPacket p = new AuthInfoOpPacket(user);
        	p.setTo(packet.friendQQ);
        	p.setSubCommand(QQ.QQ_SUB_CMD_GET_AUTH_INFO);
        	
        	QQBuddy buddy = mBuddyMap.get(friendQQ);
        	if (buddy == null) {
        		buddy = new QQBuddy(friendQQ);
        		mBuddyMap.put(friendQQ, buddy);
        	}
        	buddy.setVerifyFlag(packet.authCode);
        	
        	client.sendPacket(p);
    	}

        private void sendFriendAddAuthInfo(AuthInfoOpReplyPacket packet) {
			LayoutInflater factory = LayoutInflater.from(aQQActivity.this);
            final View authView = factory.inflate(R.layout.add_friend_auth_dialog, null);
            
			final byte[] authInfo = packet.authInfo;
			
			//获取qq号
			AuthInfoOpPacket outPacket = (AuthInfoOpPacket) client.retrieveSent(packet);
			final int qq = outPacket.getTo();
			Log.d("aQQ", "sendFriendAddAuthInfo qq= "+qq);
			
			QQBuddy buddy = mBuddyMap.get(qq);
			if (buddy.getVerifyFlag() == QQ.QQ_AUTH_NEED) {
	            new AlertDialog.Builder(aQQActivity.this)
	            .setTitle(R.string.info_add_friend)
	            .setView(authView)
	            .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() {
	                public void onClick(DialogInterface dialog, int whichButton) {
	                	String message = ((TextView)authView.findViewById(R.id.auth_edit)).getText().toString(); 
	                	client.user_SendAuth(qq, authInfo, message);
	                }
	            })
	            .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
	                public void onClick(DialogInterface dialog, int whichButton) {
	                	
	                }
	            })
	            .show();
			} else if (buddy.getVerifyFlag() == QQ.QQ_AUTH_NO) {
				client.user_SendAuth(qq, authInfo, "");
			}

        }
        
		private void processGetAuthInfoFromUrl(AuthInfoOpReplyPacket packet) {
			LayoutInflater factory = LayoutInflater.from(aQQActivity.this);
            final View authView = factory.inflate(R.layout.add_friend_auth_img_dialog, null);
            final ImageView iv = (ImageView)authView.findViewById(R.id.auth_img);
            final TextView tv = (TextView)authView.findViewById(R.id.auth_img_edit);
			
            final String url = Util.getString(packet.authInfo);
			Log.d("aQQ", "url = " + url);
			
			VerifyImage image= Utils.downloadVerifyImage(url);
			
			iv.setImageBitmap(image.getBitmap());
			final String sessionId = image.getSessionId();
			
			AuthInfoOpPacket outPacket = (AuthInfoOpPacket) client.retrieveSent(packet);
			final int qq = outPacket.getTo();
			Log.d("aQQ", "processGetAuthInfoFromUrl qq= "+qq);
			
			
            new AlertDialog.Builder(aQQActivity.this)
            .setTitle("请输入验证码")
            .setView(authView)
            .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	Log.d("aQQ", "authInfo=" + tv.getText().toString());
                	//提交验证信息
                	AuthInfoOpPacket p = new AuthInfoOpPacket(user);
                	p.setSubCommand(QQ.QQ_SUB_CMD_SUBMIT_AUTH_INFO);
                	p.setTo(qq);
                	p.setAuthString(tv.getText().toString());
                	p.setCookie(sessionId);
                	Log.d("aQQ", "auth friendQQ = " + qq);
                	Log.d("aQQ", "cookie=" + p.getCookie());
                	client.sendPacket(p);
                }
            })
            .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	
                }
            })
            .show();
		}

		private void processGroupIm(Message msg) {
			QQEvent event = (QQEvent) msg.obj;
			ReceiveIMPacket packet = (ReceiveIMPacket) event.getSource();
			ClusterIM clusterIM = packet.clusterIM;
			if (clusterIM!=null) {
				int externalId = clusterIM.externalId;
				
//				String text = Util.getString(clusterIM.messageBytes);
				String text = clusterIM.message;
				
				QQGroup qqGroup = null;
				for (int i=0; i<mQQGroups.size(); i++) {
					if (mQQGroups.get(i).getExternalId() == externalId) {
						qqGroup = mQQGroups.get(i);
						break;
					}
				}
				
				QQGroupMember sender = qqGroup.getMember(clusterIM.sender);
				sendNotification(qqGroup, sender.toString() + "：" + text);
				
				Handler handler = handlers.get(qqGroup.getClusterId());
				if (handler != null) {
					Message m = Message.obtain(msg);
					m.setTarget(handler);
					handler.sendMessage(m);
				} 
				ChatState chatState = mChatStateMap.get(qqGroup.getClusterId());
				if (chatState == null) {
					chatState = new ChatState(qqGroup);
					mChatStateMap.put(qqGroup.getClusterId(), chatState);
					mChatingAdapter = new ChatingListAdapter(aQQActivity.this);
		    		mChatingListView.setAdapter(mChatingAdapter);
				}
				chatState.addMessage(sender.getQQ(), sender.toString() + "：["+ DateFormat.format("kk:mm", clusterIM.sendTime) + "]\n" + text, true);
				
//				try {
//					message = packet.clusterIM.sender + new String(packet.clusterIM.messageBytes ,"gbk");
//				} catch (UnsupportedEncodingException e) {
//					e.printStackTrace();
//				}
			} 
//			showDialog(DIALOG_MESSAGE);
//			Toast.makeText(aQQ.this, message, Toast.LENGTH_LONG).show();
		}

    };
    
    //根据好友所在分组序号获得好友在分组列表中的位置
    private int getGroupPos(int groupSeq) {
    	int groupPos = -1;
    	int groupSize = mGroupData.size();
    	for (int i=0; i<groupSize; i++) {
			if(mGroupData.get(i).getGroupSeq() == groupSeq) {
				groupPos = i;
				break;
			}
		}
    	return groupPos;
    }

	private void updateBuddyRemark(FriendDataOpPacket packet) {
		int qq = packet.getQQ();
		QQBuddy friend = mBuddyMap.get(qq);
		
		if (friend!=null) {
			friend.setName(packet.getRemark().name);

			ChatState chat = mChatStateMap.get(qq);
			if (chat != null) {
				chat.getBuddy().setName(packet.getRemark().name);
			}
		}
		mFriendsAdapter.notifyDataSetChanged();
		mChatingAdapter.notifyDataSetChanged();
		
	}
	private void processFriendAddOk(int buddyQQ) {
		final int qq = buddyQQ;
		LayoutInflater factory = LayoutInflater.from(this);
        final View view = factory.inflate(R.layout.add_friend_ok_dialog, null);
        
        final List<String> list = new ArrayList<String>();
		for (int i=0; i<mGroupData.size(); i++) {
			list.add(mGroupData.get(i).getGroupName());
		}
        
        final Spinner spinner = (Spinner) view.findViewById(R.id.group_spinner);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>( this, android.R.layout.simple_spinner_item, list);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        
        new AlertDialog.Builder(aQQActivity.this)
//            .setIcon(R.drawable.alert_dialog_icon)
            .setTitle(getResources().getString(R.string.info_add_friend) + " " + qq)
            .setView(view)
            .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	String remark = ((TextView)view.findViewById(R.id.remark_edit)).getText().toString(); 
                	//上传好友分组
                	int pos = spinner.getSelectedItemPosition();
                	int group = mGroupData.get(pos).getGroupSeq();
                	client.user_AddToList(group, qq);
                	//上传备注
                	FriendRemark friendRemark = new FriendRemark();
                	friendRemark.name = remark;
                	client.user_UploadRemark(qq, friendRemark);
                	//获取好友信息
                	QQBuddy buddy = mBuddyMap.get(qq);
                	if (buddy == null) {
                		buddy = new QQBuddy(qq);
                		buddy.setName(remark);
                		mBuddyMap.put(qq, buddy);
                		client.user_GetInfo(qq);
                	}
                	mChildData.get(pos).move(buddy);
                	mBuddyGroupMap.put(qq, pos);
                	mFriendsAdapter.notifyDataSetChanged();
                	
                }
            })
            .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	
                }
            })
            .show();
	}
	/**
     * 处理好友备注
     * @param packet
     */
    protected synchronized void processFriendsRemark(FriendDataOpReplyPacket packet) {
    	QQService.hasRemark = packet.hasRemark;
    	if (QQService.hasRemark) {
    		QQService.friendsRemarkPage ++;
    		client.user_GetRemarks(QQService.friendsRemarkPage);
    	}
    	
    	if (mBuddyGroupMap==null) {
    		return;
    	}
    	
    	Map<Integer, FriendRemark> map = packet.remarks;
    	
    	Iterator<Map.Entry<Integer,FriendRemark>> iterator = map.entrySet().iterator();
    	
    	while (iterator.hasNext()) {
    		Map.Entry<Integer,FriendRemark> entry = iterator.next();
    		int qq = entry.getKey();
    		
    		QQBuddy buddy = mBuddyMap.get(qq);
    		if ( buddy != null) {
    			buddy.setFriendRemark(entry.getValue());
    		} else  {
    			//TODO 没有找到，加入陌生人
    		}
    	}
    	fillAutoCompleteEdit();
	}

	private void processNormalMessage(Message msg) {
		QQEvent event = (QQEvent) msg.obj;
    	ReceiveIMPacket packet = (ReceiveIMPacket) event.getSource();
		if (packet.normalHeader!=null) {
			int qq = packet.normalHeader.sender;
			QQBuddy buddy = mBuddyMap.get(qq);
			if (buddy == null) {
				buddy = new QQBuddy(qq);
			}
			
			String text = Utils.parseIMMessage(aQQActivity.this,packet.normalIM.messages);
			sendNotification(buddy, text);
			
			Handler handler = handlers.get(qq);
			if (handler != null) {
				Message m = Message.obtain(msg);
				m.setTarget(handler);
				handler.sendMessage(m);
			}
			
			ChatState chatState = mChatStateMap.get(qq);
			if (chatState == null) {
				chatState = new ChatState(buddy);
				mChatStateMap.put(qq, chatState);
				mChatingAdapter = new ChatingListAdapter(aQQActivity.this);
	    		mChatingListView.setAdapter(mChatingAdapter);
			}
			chatState.addMessage(buddy.getQQ(), buddy.toString() + "：["+ DateFormat.format("kk:mm", packet.normalHeader.sendTime) + "]\n" + text, true);
			
		}
	}

	protected void processFriendChangeStatus(FriendChangeStatusPacket packet) {
    	if (mBuddyGroupMap==null || mChildData== null) {
    		return;
    	}
    	changeFriendStatus(packet.friendQQ , packet.status);
    	changeChatingStatus(packet.friendQQ , packet.status);
    	mChatingAdapter.notifyDataSetChanged();
    	mFriendsAdapter.notifyDataSetChanged();
	}
    
	//改变正在聊天的好友状态
    private void changeChatingStatus(int qq, byte status) {
    	ChatState chat  = mChatStateMap.get(qq);
    	if (chat!=null) {
    		chat.getBuddy().setStatus(status);
    	}
//    	mChatingListView.setAdapter(mChatingAdapter);
    }
    
	private void changeFriendStatus(int qq, byte status) {
    	if (mBuddyGroupMap==null || mBuddyGroupMap.get(qq) == null) {
    		return;
    	}
    	int groupPos = getGroupPos(mBuddyGroupMap.get(qq));
		if(groupPos == -1) {
			return;
		}
		
		BuddyGroup group = mFriendsAdapter.getGroup(groupPos);
		//设置分组的在线好友数量
		QQBuddy buddy = mBuddyMap.get(qq);
		if (buddy == null) {
			return;
		}
		
		byte originalStatus = buddy.getStatus();
		if (originalStatus != status) {
			if (status == QQ.QQ_STATUS_OFFLINE) {
				group.setOnline(group.getOnline() - 1);
			} 
			if (originalStatus == QQ.QQ_STATUS_OFFLINE) {
				group.setOnline(group.getOnline() + 1);
			}
			buddy.setStatus(status);
			
			TextView view = mFriendsAdapter.mGroupViews.get(groupPos);
			if (view != null) {
				view.setText(group.getGroupName() + "[" + group.getOnline() + "/" + mFriendsAdapter.getChildrenCount(groupPos) + "]");
			}
			SortList<QQBuddy> children = mChildData.get(groupPos);
			if (children!=null) {
				children.move(buddy);
			}
		}
		
    }


	private synchronized void processOnlineFriends(GetOnlineOpReplyPacket packet) {
    	List<FriendOnlineEntry> onlineFriends = packet.onlineFriends;
    	int size = onlineFriends.size();
    	for (int i=0; i<size; i++) {
    		FriendStatus freindStatus = onlineFriends.get(i).status;
    		int qq = freindStatus.qqNum;
    		byte status = freindStatus.status;
    		changeFriendStatus(qq, status);
    	}
    	if (!packet.finished) {
			client.user_GetOnline(packet.position);
		}
    	mFriendsAdapter.notifyDataSetChanged();
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
        case DIALOG_MESSAGE:
            return new AlertDialog.Builder(aQQActivity.this)
			.setMessage(message)
			.setPositiveButton(R.string.button_confirm,
			new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface arg0, int arg1) {

				}
			}).create();
        case DIALOG_ADD_FRIEND:
        	LayoutInflater factory = LayoutInflater.from(this);
            final View textEntryView = factory.inflate(R.layout.add_friend_dialog, null);
            
            return new AlertDialog.Builder(aQQActivity.this)
//                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(R.string.info_add_friend)
                .setView(textEntryView)
                .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    	int qq = Integer.parseInt(((TextView)textEntryView.findViewById(R.id.qq_edit)).getText().toString()); 
                    	QQBuddy buddy = mBuddyMap.get(qq);
                    	if (buddy == null) {
                    		buddy = new QQBuddy(qq);
                    		mBuddyMap.put(qq, buddy);
                    	}
                    	client.user_Add(qq);
                    }
                })
                .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    	
                    }
                })
                .create();
        case DIALOG_SELECT_GROUP: //选择好友分组
        	factory = LayoutInflater.from(this);
            final View view = factory.inflate(R.layout.select_group_dialog, null);
            
            final List<String> list = new ArrayList<String>();
    		for (int i=0; i<mGroupData.size(); i++) {
    			list.add(mGroupData.get(i).getGroupName());
    		}
            
            final Spinner spinner = (Spinner) view.findViewById(R.id.group_spinner);
            ArrayAdapter<String> adapter = new ArrayAdapter<String>( this, android.R.layout.simple_spinner_item, list);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinner.setAdapter(adapter);
            return new AlertDialog.Builder(aQQActivity.this)
//                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(R.string.title_choose)
                .setView(view)
                .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    	//上传好友分组
                    	int pos = spinner.getSelectedItemPosition();
                    	int group = mGroupData.get(pos).getGroupSeq();
                    	client.user_AddToList(group, operateQQ);
                    	
                    	//获得qq号所在的原分组
                    	int originalGroupPos = mBuddyGroupMap.get(operateQQ);
                    	QQBuddy friend = mBuddyMap.get(operateQQ);
                        mChildData.get(originalGroupPos).remove(friend);
                    	
                    	mChildData.get(pos).move(friend);
                    	mBuddyGroupMap.put(operateQQ, pos);
                    	//设置分组的在线好友数量
        				byte status = friend.getStatus();
        				if (status != QQ.QQ_STATUS_OFFLINE) { //如果好友不是离线状态
        					//移入分组的在线数量加一
        					mGroupData.get(pos).setOnline(mGroupData.get(pos).getOnline() + 1);
        					//移除分组的在线数量减一
        					mGroupData.get(originalGroupPos).setOnline(mGroupData.get(originalGroupPos).getOnline() - 1);
    					} 
                    	mFriendsAdapter.notifyDataSetChanged();
                    }
                })
                .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    	
                    }
                })
                .create();
        case DIALOG_MODIFY_REMARK: //修改好友备注
        	factory = LayoutInflater.from(this);
            final View modifyRemarkView = factory.inflate(R.layout.modify_remark_dialog, null);
            return new AlertDialog.Builder(aQQActivity.this)
//                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(R.string.title_input)
                .setView(modifyRemarkView)
                .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    	String remark = ((TextView)modifyRemarkView.findViewById(R.id.remark_edit)).getText().toString(); 
                    	//上传备注
                    	FriendRemark friendRemark = new FriendRemark();
                    	friendRemark.name = remark;
                    	client.user_UploadRemark(operateQQ, friendRemark);
                    }
                })
                .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    	
                    }
                })
                .create();
        case DIALOG_ABOUT:
        	return new AlertDialog.Builder(aQQActivity.this)
        		.setTitle(R.string.menu_about)
        		.setMessage(R.string.info_about)
        		.setPositiveButton(R.string.button_confirm,
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface arg0, int arg1) {
							
						}
					}).create();
		}
		return null;
	}
	
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		super.onPrepareDialog(id, dialog);
		switch(id) {
		case DIALOG_MESSAGE:
			AlertDialog alert = (AlertDialog) dialog;
			alert.setMessage(message);
			break;
		case DIALOG_SELECT_GROUP: //选择好友分组
			((Spinner)dialog.findViewById(R.id.group_spinner)).setSelection(0);
			break;
		case DIALOG_ADD_FRIEND:
			((TextView)dialog.findViewById(R.id.qq_edit)).setText("");
        	break;
		case DIALOG_MODIFY_REMARK: //修改好友备注
			((TextView)dialog.findViewById(R.id.remark_edit)).setText("");
			break;
		}
	}

	@Override
	protected void onDestroy() {
		//取消绑定QQService
		unbindService(mConnection);
		super.onDestroy();
		
//		if (user != null && user.isLoggedIn()) {
//			client.logout();
//		}
//		client.release();
	}
	
	
	public static void bindHandler(int id, Handler handler) {
		handlers.put(id, handler);
	}
	
	public static void removeHandler(int id) {
		Handler curHandler = handlers.get(id);
		if (curHandler!=null) {
			curHandler.sendEmptyMessage(-1);
			handlers.remove(id);
		}
	}
	
	/*自定义布局组件中用于显示数据的组件类**/
	public class ClusterViewHolder {
		TextView mClusterId;
		TextView mName;
		TextView mDescription;
		TextView mNotice;
	}
	
	//QQ群列表
	public class QQGroupListAdapter extends BaseAdapter {
		private Context mcContext;
		private LayoutInflater mInflater;
		private List<QQGroup> mQQGroupData;

		public QQGroupListAdapter(Context context) {
			this.mcContext = context;
			mInflater = LayoutInflater.from(this.mcContext);
			mQQGroupData = mQQGroups;
		} 
		
		public int getCount() {
			return mQQGroupData.size();
		}

		public QQGroup getItem(int pos) {
			return mQQGroupData.get(pos);
		}

		public long getItemId(int pos) {
			return pos;
		}

		public View getView(int pos, View convertView, ViewGroup vg) {
        	final ClusterViewHolder holder;
        	if (convertView == null) {
        	    //使用XML文件填充整个布局
        	    convertView = mInflater.inflate(R.layout.user_list, null);
        	    holder = new ClusterViewHolder();//生成存放数据的组件模型
        	    holder.mName = (TextView) convertView.findViewById(R.id.nick);
        	    holder.mDescription = (TextView) convertView.findViewById(R.id.status);
        	    convertView.setTag(holder); //将存放数据的组件模型加入到整个View视图中
        	} else {
        	     holder = (ClusterViewHolder) convertView.getTag();
        	}
        	QQGroup qqGroup = getItem(pos);
        	holder.mName.setText(qqGroup.getName());
        	holder.mDescription.setText(qqGroup.getDescription());
        	
			return convertView;

		}
	}
	
	public class ChatingListAdapter extends BaseAdapter {
		private Context mcContext;
		private LayoutInflater mInflater;
		private List<ChatState> mChatingData;

		public ChatingListAdapter(Context context) {
			this.mcContext = context;
			mInflater = LayoutInflater.from(this.mcContext);
			mChatingData = new ArrayList<ChatState>();
			
			if (mChatStateMap!=null && mChatStateMap.entrySet()!=null) {
				Iterator<Entry<Integer, ChatState>> iterator = mChatStateMap.entrySet().iterator();
				while(iterator.hasNext()) {
					Entry<Integer, ChatState> entry = iterator.next();
					mChatingData.add(entry.getValue());
				}
			}
		} 
		
		public int getCount() {
			return mChatingData.size();
		}

		public ChatState getItem(int pos) {
			return mChatingData.get(pos);
		}

		public long getItemId(int pos) {
			return pos;
		}
		
		public View getView(int pos, View convertView, ViewGroup vg) {
			String tag = "getView";
        	final ViewHolder holder;
        	if (convertView == null) {
        	    //使用XML文件填充整个布局
        	    convertView = mInflater.inflate(R.layout.user_list, null);
        	    holder = new ViewHolder();//生成存放数据的组件模型
        	    holder.mNick = (TextView) convertView.findViewById(R.id.nick);
        	    holder.mStatus = (TextView) convertView.findViewById(R.id.status);
        	    holder.mUserHead = (ImageView) convertView.findViewById(R.id.user_head);
        	    holder.mMessage = (TextView) convertView.findViewById(R.id.message); 
//        	    holder.mStatusIcon = (ImageView) convertView.findViewById(R.id.status_icon);
        	    convertView.setTag(holder); //将存放数据的组件模型加入到整个View视图中
        	    getItem(pos).setHolder(holder);
        	} else {
        	     holder = (ViewHolder) convertView.getTag();
        	}
        	if (getItem(pos).getType() == 1) { //好友聊天
        		QQBuddy buddy = getItem(pos).getBuddy();
        		byte status = buddy.getStatus();
            	holder.mNick.setText(buddy.toString());
            	holder.mMessage.setText("(" + getItem(pos).getUnread() + ")");
            	holder.mStatus.setText(Utils.getStatus(status));
            	
            	setListItemView(holder, status);
            	
//            	holder.mUserHead.setImageBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.delete));
            	holder.mUserHead.setOnClickListener(new OnClickListener(){
            	     public void onClick(View v) {
//    					holder.mNick.setBackgroundColor(Color.WHITE);
//    					holder.mUserHead.setVisibility(View.VISIBLE);
    				}
    			});
        	} else { //群聊天
        		QQGroup qqGroup = getItem(pos).getQQGroup();
            	holder.mNick.setText(qqGroup.getName());
            	holder.mMessage.setText("(" + getItem(pos).getUnread() + ")");
            	holder.mStatus.setText(qqGroup.getDescription());
        	}
			return convertView;

		}
	}
	
    public class MyExpandableListAdapter extends BaseExpandableListAdapter {
//        private List<Map<String, String>> mOriginalGroups;
//        private List<List<Map<String, String>>> mOriginalChildren;
        private LayoutInflater mInflater = null;
        private Map<Integer, TextView> mGroupViews;
        private List<BuddyGroup> mGroups;
        private List<SortList<QQBuddy>> mChildren;
        
        public MyExpandableListAdapter(List<BuddyGroup> groups, 
        		List<SortList<QQBuddy>> children) {
        	this.mGroups = groups;
//        	this.mOriginalChildren = children;
        	this.mChildren = children;
//        	this.mOriginalGroups = groups;
        	
        	mInflater = LayoutInflater.from(aQQActivity.this);
        	mGroupViews = new HashMap<Integer, TextView>();
        }
        
        public QQBuddy getChild(int groupPosition, int childPosition) {
            return (QQBuddy)mChildren.get(groupPosition).get(childPosition);
        }

        public long getChildId(int groupPosition, int childPosition) {
            return childPosition;
        }

        public int getChildrenCount(int groupPosition) {
            return mChildren.get(groupPosition).size();
        }

        public TextView getGenericView() {
            // Layout parameters for the ExpandableListView
            AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT, 50);

            TextView textView = new TextView(aQQActivity.this);
            textView.setLayoutParams(lp);
            textView.setTextSize(18);
            // Center the text vertically
            textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
            // Set the text starting position
            textView.setPadding(36, 0, 0, 0);
            return textView;
        }
        
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                View convertView, ViewGroup parent) {
        	final ViewHolder holder;
        	final QQBuddy child = getChild(groupPosition, childPosition);
        	if (convertView == null) {
        	    //使用XML文件填充整个布局
        	    convertView = mInflater.inflate(R.layout.user_list, null);
        	    holder = new ViewHolder();//生成存放数据的组件模型
        	    
        	    holder.mNick = (TextView) convertView.findViewById(R.id.nick);
        	    holder.mMessage = (TextView) convertView.findViewById(R.id.message); 
        	    holder.mStatus = (TextView) convertView.findViewById(R.id.status);
        	    holder.mUserHead = (ImageView) convertView.findViewById(R.id.user_head);
//        	    holder.mStatusIcon = (ImageView) convertView.findViewById(R.id.status_icon);
        	    convertView.setTag(holder); //将存放数据的组件模型加入到整个View视图中
        	} else {
        	     holder = (ViewHolder) convertView.getTag();
        	}
        	
        	byte status = child.getStatus();
        	holder.mNick.setText(child.toString());
        	holder.mStatus.setText(Utils.getStatus(status));
        	
        	setListItemView(holder, status);
        	
        	holder.mUserHead.setOnClickListener(new OnClickListener(){
        	     public void onClick(View v) {// 设置按钮点击事件
//					holder.mNick.setBackgroundColor(Color.WHITE);
//					holder.mUserHead.setVisibility(View.VISIBLE);
        	    	 
     				if (user==null || !user.isLoggedIn()) {
    					Toast.makeText(aQQActivity.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
    					return;
    				}
    				
    				new AlertDialog.Builder(aQQActivity.this).setTitle(child.toString()).setItems(R.array.item_operate,
    					new DialogInterface.OnClickListener() {
    						public void onClick(DialogInterface dialog, int which) {
    							switch (which) {
    							case 0:
    								//开启一个聊天窗口
    								startChatWindow(child);
    								break;
    							case 1:
    								operateQQ = child.getQQ();
    								showDialog(DIALOG_SELECT_GROUP);
    								break;
    							case 2:
    								operateQQ = child.getQQ();
    								showDialog(DIALOG_MODIFY_REMARK);
    								break;
    							}
    						}
    					}).setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
    	                    public void onClick(DialogInterface dialog, int whichButton) {
    	                    }
    	                }).show();
				}
			});
        	
//        	convertView.setOnClickListener(new OnClickListener(){
//				public void onClick(View v) {
//					if (user==null || !user.isLoggedIn()) {
//						Toast.makeText(aQQ.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
//					} else {
//						//开启一个聊天窗口
//						startChatWindow(child);
//					}
//				}
//        	});
//        	
//        	convertView.setOnLongClickListener(new OnLongClickListener(){
//				public boolean onLongClick(View v) {
//					if (user==null || !user.isLoggedIn()) {
//						Toast.makeText(aQQ.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
//						return false;
//					}
//					new AlertDialog.Builder(aQQ.this).setTitle(R.string.title_choose).setItems(R.array.item_operate,
//						new DialogInterface.OnClickListener() {
//							public void onClick(DialogInterface dialog, int which) {
//								switch (which) {
//								case 0:
//									//开启一个聊天窗口
//									startChatWindow(child);
//									break;
//								case 1:
//									friendQQ = child.getQQ();
//									showDialog(DIALOG_SELECT_GROUP);
//									break;
//								case 2:
//									friendQQ = child.getQQ();
//									showDialog(DIALOG_MODIFY_REMARK);
//									break;
//								}
//							}
//						}).setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
//		                    public void onClick(DialogInterface dialog, int whichButton) {
//		                    }
//		                }).show();
//					return true;
//				}
//        	});
        	
			return convertView;
        }

        public BuddyGroup getGroup(int groupPosition) {
            return mGroups==null?null:mGroups.get(groupPosition);
        }

        public int getGroupCount() {
            return mGroups==null?0:mGroups.size();
        }

        public long getGroupId(int groupPosition) {
            return groupPosition;
        }

        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                ViewGroup parent) {
            TextView textView = getGenericView();
            textView.setText(getGroup(groupPosition).getGroupName() + "[" + getGroup(groupPosition).getOnline() + "/" + mChildren.get(groupPosition).size() + "]");
            mGroupViews.put(groupPosition, textView);
            return textView;
        }

        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }

        public boolean hasStableIds() {
            return true;
        }
		
//		public void filter(String prefix) {
//			if (prefix == null || prefix.length() == 0) {
//				mChildren = mOriginalChildren;
//			} else {
//				String prefixString = prefix.toString().toLowerCase();
//
//				final List<List<Map<String, String>>> values = mChildren;
//				final int count = values.size();
//
//				final List<List<Map<String, String>>> newValues = new ArrayList<List<Map<String, String>>>(count);
//
//				for (int i = 0; i < count; i++) {
//					final List<Map<String, String>> newChildrenList = new ArrayList<Map<String, String>>();
//					final List<Map<String, String>> value = values.get(i);
//					final int size = value.size();
//					for (int j=0; j<size; j++) {
//						final Map<String, String> map = value.get(j);
//						final String qq = map.get(QQ_NUM);
//						final String nick = map.get(NICK).toLowerCase();
//						
//						if (qq.startsWith(prefixString) || nick.startsWith(prefixString)) {
//							final Map<String, String> newMap = new HashMap<String,String>();
//							newMap.putAll(map);
//							newChildrenList.add(newMap);
//						} 
//					}
//					newValues.add(newChildrenList);
//				}
//				mChildren = newValues;
//			}
//		}

    }
    
    private void setListItemView(final ViewHolder holder, byte status) {
    	switch (status) {
    	case QQ.QQ_STATUS_ONLINE:
    		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_online));
    		holder.mNick.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
			holder.mMessage.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
			holder.mStatus.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
    		break;
    	case QQ.QQ_STATUS_QME:
    		holder.mNick.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
			holder.mMessage.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
			holder.mStatus.setTextColor(getResources().getColor(android.R.color.primary_text_dark));
			holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_qme));
    		break;
    	case QQ.QQ_STATUS_OFFLINE:
    		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_offline));
    		break;
    	case QQ.QQ_STATUS_AWAY:
    		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_away));
    		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
    		break;
    	case QQ.QQ_STATUS_BUSY:
    		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_busy));
    		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
    		break;
    	case QQ.QQ_STATUS_QUIET:
    		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_quiet));
    		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_dark));
    		break;
    	}
	}
    
    private void sendNotification(QQBuddy friend, String text) {
    	Intent intent = new Intent(this, ChatWindowActivity.class);
    	intent.putExtra("FRIEND", friend);
    	intent.putExtra("MYQQ", user.getQQ());
    	PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        final Notification notification = new Notification(
                R.drawable.message,          // the icon for the status bar
                text,                        // the text to display in the ticker
                System.currentTimeMillis()); // the timestamp for the notification

        notification.setLatestEventInfo(
                this,                        // the context to use
                friend.toString(),
                                             // the title for the notification
                text,                        // the details to display in the notification
                contentIntent);              // the contentIntent (see above)

        if (isMute) {
        	if (isVibrate) {
        		notification.defaults = Notification.DEFAULT_VIBRATE;
        	}
        } else {
        	notification.defaults = Notification.DEFAULT_SOUND;
        }
        
        
        mNotificationManager.notify(NOTIFICATION_FRIEND_CHAT, notification);
    }
    
    private void sendNotification(QQGroup qqGroup, String text) {
    	Intent intent = new Intent(this, GroupChatWindowActivity.class);
    	intent.putExtra("QQ_GROUP", qqGroup);
    	intent.putExtra("MYQQ", user.getQQ());
    	PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        final Notification notification = new Notification(R.drawable.message, text, 
        		System.currentTimeMillis());

        notification.setLatestEventInfo(
                this, qqGroup.getName(), text, contentIntent);
        
        if (isMute) {
        	if (isVibrate) {
        		notification.defaults = Notification.DEFAULT_VIBRATE;
        	}
        } else {
        	notification.defaults = Notification.DEFAULT_SOUND;
        }
        
        mNotificationManager.notify(NOTIFICATION_QQGROUP_CHAT, notification);
    }
    
//    @Override
//    public boolean onSearchRequested() {
//        // If your application absolutely must disable search, do it here.
////        if (mMenuMode.getSelectedItemPosition() == MENUMODE_DISABLED) {
////            return false;
////        }
//        
//        // It's possible to prefill the query string before launching the search
//        // UI.  For this demo, we simply copy it from the user input field.
//        // For most applications, you can simply pass null to startSearch() to
//        // open the UI with an empty query string.
////        final String queryPrefill = "";
//        
//        // Next, set up a bundle to send context-specific search data (if any)
//        // The bundle can contain any number of elements, using any number of keys;
//        // For this Api Demo we copy a string from the user input field, and store
//        // it in the bundle as a string with the key "demo_key".
//        // For most applications, you can simply pass null to startSearch().
////        Bundle appDataBundle = null;
////        final String queryAppDataString = "";
////        if (queryAppDataString != null) {
////            appDataBundle = new Bundle();
////            appDataBundle.putString("demo_key", queryAppDataString);
////        }
//        
//        // Now call the Activity member function that invokes the Search Manager UI.
//        startSearch("", false, null, false); 
//        
//        // Returning true indicates that we did launch the search, instead of blocking it.
//        return true;
//    }
    
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
    	 mMenu = menu;
         
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.menu_main, menu);
         
         return true;
    }
    
    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
        switch (item.getItemId()) { 
        	case R.id.menu_search:
        		View view = (View)findViewById(R.id.search_friends_view);
        		if (view.getVisibility() == View.INVISIBLE) {
        			view.setVisibility(View.VISIBLE);
        		} else {
        			view.setVisibility(View.INVISIBLE);
        		}
	            break;
        	case R.id.menu_logout:
        		mBoundService.stopSelf();
        		if (user!=null && user.isLoggedIn()) {
            		client.logout();
            	}
            	client.release();
        		setResult(RESULT_OK);
        		finish();
	            break;
        	case R.id.menu_add:
        		showDialog(DIALOG_ADD_FRIEND);
	            break;
        	case R.id.menu_about:
        		showDialog(DIALOG_ABOUT);
	            break;
        }
        return super.onOptionsItemSelected(item);
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
        	if (mSearchFriendsView.getVisibility() == View.VISIBLE) {
        		mSearchFriendsView.setVisibility(View.INVISIBLE);
        		return true;
        	} else {
//              showDialog(DIALOG_CONFIRM);
            	setResult(RESULT_OK);
    			finish();
                return true;
        	}

        }
        return super.onKeyDown(keyCode, event);
    }
    
    /**
     * @author Michael
     *
     */
    public class FriendsListAdapter extends BaseAdapter implements Filterable {
    	private Context mContext = null;
    	private List<QQBuddy> mOriginalFriends = null;
    	private List<QQBuddy> mFriends = null;
    	private Filter mFilter;
    	

		public List<QQBuddy> getFriends() {
			return mFriends;
		}

		public FriendsListAdapter(Context context, List<QQBuddy> friends) {
        	this.mContext = context;
        	this.mOriginalFriends = friends;
        	this.mFriends = friends; 
        }

		public Filter getFilter() {
			if (mFilter == null) {
				mFilter = new ListFilter();
			}
			return mFilter;
		}
		
		private class ListFilter extends Filter {

			@Override
			protected FilterResults performFiltering(CharSequence prefix) {
				FilterResults results = new FilterResults(); 
				
				if (mOriginalFriends == null) {
					mOriginalFriends = new ArrayList<QQBuddy>();
				}
				if (prefix == null || prefix.length() == 0) {
					List<QQBuddy> list = new ArrayList<QQBuddy>(mOriginalFriends);
					results.values = list;
				    results.count = list.size();  
				} else {
					String prefixString = prefix.toString().toLowerCase();

					final List<QQBuddy> values = mOriginalFriends;
					final int count = values.size();  

					final List<QQBuddy> newValues = new ArrayList<QQBuddy>(count);

					for (int j=0; j<count; j++) {
						final QQBuddy value = values.get(j);
						final String qq = "" + value.getQQ();
						final String nick = value.getNick().toLowerCase();
						final String name = value.getName()==null?"":value.getName().toLowerCase();
//						final String namePinyin = PinYin.getPinYinHeadChar(name);
//						final String nickPinyin = PinYin.getPinYinHeadChar(nick);
						
						if (/*namePinyin.startsWith(prefixString) || nickPinyin.startsWith(prefixString) 
								|| */qq.indexOf(prefixString)>-1 || nick.indexOf(prefixString)>-1 
								|| name.indexOf(prefixString)>-1) {
							newValues.add(value);
						} 
					}
					results.values = newValues;  
				    results.count = newValues.size();
				}
				return results;
			}

			@Override
			protected void publishResults(CharSequence constraint,
					FilterResults results) {
				mFriends = (List<QQBuddy>) results.values;
				if (results.count > 0) {
					notifyDataSetChanged();
				} else {
					notifyDataSetInvalidated();
				}  
			}
		}

		public int getCount() {
			return mFriends.size();
		}

		public QQBuddy getItem(int position) {
			QQBuddy friend = mFriends.get(position);
 			return friend ;
		}

		public long getItemId(int position) {
			return position;
		}
		
		public View getView(int pos, View convertView, ViewGroup vg) {
			final LayoutInflater inflater = LayoutInflater.from(mContext);
        	final ViewHolder holder;
        	if (convertView == null) {
        	    //使用XML文件填充整个布局
        	    convertView = inflater.inflate(R.layout.user_list, null);
        	    holder = new ViewHolder();//生成存放数据的组件模型
        	    holder.mNick = (TextView) convertView.findViewById(R.id.nick);
        	    holder.mStatus = (TextView) convertView.findViewById(R.id.status);
        	    holder.mUserHead = (ImageView) convertView.findViewById(R.id.user_head);
        	    holder.mMessage = (TextView) convertView.findViewById(R.id.message);
//        	    holder.mStatusIcon = (ImageView) convertView.findViewById(R.id.status_icon);
        	    convertView.setTag(holder); //将存放数据的组件模型加入到整个View视图中
        	} else {
        	     holder = (ViewHolder) convertView.getTag();
        	}
        	final QQBuddy friend = getItem(pos);
        	byte status = friend.getStatus();
        	holder.mNick.setText(friend.toString());
        	holder.mStatus.setText(Utils.getStatus(status));
        	
        	switch(status) {
        	case QQ.QQ_STATUS_ONLINE:
        		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_online));
        		holder.mNick.setTextColor(getResources().getColor(android.R.color.primary_text_light));
    			holder.mMessage.setTextColor(getResources().getColor(android.R.color.primary_text_light));
    			holder.mStatus.setTextColor(getResources().getColor(android.R.color.primary_text_light));
        		break;
        	case QQ.QQ_STATUS_QME:
        		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_qme));
    			holder.mNick.setTextColor(getResources().getColor(android.R.color.primary_text_light));
    			holder.mMessage.setTextColor(getResources().getColor(android.R.color.primary_text_light));
    			holder.mStatus.setTextColor(getResources().getColor(android.R.color.primary_text_light));
    			break;
        	case QQ.QQ_STATUS_OFFLINE:
    			holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_offline));
    			break;
        	case QQ.QQ_STATUS_AWAY:
        		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_away));
        		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			break;
        	case QQ.QQ_STATUS_BUSY:
        		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_busy));
        		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			break;
        	case QQ.QQ_STATUS_QUIET:
        		holder.mUserHead.setImageDrawable(getResources().getDrawable(R.drawable.head_quiet));
        		holder.mNick.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mMessage.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			holder.mStatus.setTextColor(getResources().getColor(android.R.color.secondary_text_light));
    			break;
    		}
        	
        	holder.mUserHead.setOnClickListener(new OnClickListener(){
        		public void onClick(View v) {// 设置按钮点击事件
	    			if (user==null || !user.isLoggedIn()) {
	   					Toast.makeText(aQQActivity.this, "未登录，请重新登录。", Toast.LENGTH_SHORT).show();
	   					return;
	   				}
	   				
	   				new AlertDialog.Builder(aQQActivity.this).setTitle(friend.toString()).setItems(R.array.item_operate,
	   					new DialogInterface.OnClickListener() {
	   						public void onClick(DialogInterface dialog, int which) {
	   							switch (which) {
	   							case 0:
	   								//开启一个聊天窗口
	   								startChatWindow(friend);
	   								break;
	   							case 1:
	   								operateQQ = friend.getQQ();
	   								showDialog(DIALOG_SELECT_GROUP);
	   								break;
	   							case 2:
	   								operateQQ = friend.getQQ();
	   								showDialog(DIALOG_MODIFY_REMARK);
	   								break;
	   							}
	   						}
	   					}).setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
	   	                    public void onClick(DialogInterface dialog, int whichButton) {
	   	                    }
	   	                }).show();
	   				mSearchEdit.setText("");
				}
			});
        	
			return convertView;
		}
    }
    
}
